/*++

Copyright (c) 2007  Microsoft Corporation 

Filename: 

    Document.cs

Abstract: 

    Interface for Visio document
     
--*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Globalization;
using Visio = Microsoft.Office.Interop.Visio;
using System.IO;
using System.Diagnostics;

namespace NRTMAddIn
{
    class Document
    {
        #region public / private variables
        
        //Menu for the current document
        public NRTMMenu docMenu = null;
        
        //Visio document
        private Visio.Document visioDocument = null;

        //Option (SCOM or WMI) used to create current document
        public Global.InputDataOption ipOption = Global.InputDataOption.ActiveShape;

        //Status window and status form
        private StatusDlg m_statusDlg;
        private AddonWindowWrapper m_statusWindow;

        //Report window and report form
        private ReportDlg m_reportDlg;
        private AddonWindowWrapper m_reportWindow;

        //Flag to indicate if current document is NRTM configured
        bool nrtmConfigured;

        //Flag set when document is saved
        bool documentSaved;

        //Flag set while disk monitoring is on
        internal bool diskMonitoringOn;

        //Flag set while diagram generation is on
        internal bool diagramGenerationOn;

        //Save monitoring status before document save
        string monitorStatus = string.Empty;

        //Monitor thread
        private Thread nrtmMonitorThread;

        //Diagram generation thread
        private Thread nrtmDiagramThread;

        //Unique ID for the document
        internal string UniqueID;

        //Object to store data tables containing monitoring data
        private CreateTables monitorDB;

        //Object for monitor class
        private Monitor monitorMach;

        #endregion public / private variables

        #region Properties

        public CreateTables MonitorDB
        {
            get
            {
                return monitorDB;
            }
        }

        public Visio.Document VisioDocument
        {
            get
            {
                return visioDocument;
            }            
        }

        public Thread NrtmDiagramThread
        {            
            set
            {
                nrtmDiagramThread = value;
            }
        }

        /// <summary>
        /// Property to get instance of status window
        /// </summary>
        internal AddonWindowWrapper StatusWindow
        {
            get
            {
                try
                {
                    if (m_statusDlg == null)
                    {
                        m_statusDlg = new StatusDlg();
                        m_statusDlg.NRTMDocument = this;
                    }

                    if (m_statusWindow == null)
                    {
                        m_statusWindow = new AddonWindowWrapper(false);

                        m_statusWindow.FormToShow = m_statusDlg;

                        // find the window this document is hosted in
                        foreach (Visio.Window nextWindow in Global.VisioApp.Windows)
                        {
                            if (nextWindow.Type == (short)Visio.VisWinTypes.visDrawing)
                            {
                                if (nextWindow.Document == this.visioDocument)
                                {
                                    // we found the window
                                    m_statusWindow.ShowWindow(nextWindow, AddonWindowConstants.NrtmAddonWindowMergeId, 1);
                                    m_statusWindow.WindowCaption = Global.GetResourceString("StatusWindow_Caption");
                                    m_statusWindow.Visible = false;
                                    m_statusWindow.Terminate += new AddonWindowWrapper.TerminateEventHandler(this.StatusWindowClosed);

                                    break;
                                }
                            }
                        }
                    }
                }
                catch (NrtmException ex)
                {
                    //Exception from sub function. Pass on to entry point
                    throw new NrtmException("StatusWindow", ex.InnerException);
                }
                catch (Exception ex)
                {
                    //Exception from current function
                    throw new NrtmException("StatusWindow", ex);
                }
                // return the status window
                return m_statusWindow;
            }
        }

        /// <summary>
        /// Property to get instance of report window
        /// </summary>
        internal AddonWindowWrapper ReportWindow
        {
            get
            {
                try
                {
                    if (m_reportDlg == null)
                    {
                        m_reportDlg = new ReportDlg();
                        m_reportDlg.NRTMDocument = this;
                    }
                    if (m_reportWindow == null)
                    {
                        m_reportWindow = new AddonWindowWrapper(false);

                        m_reportWindow.FormToShow = m_reportDlg;

                        // find the window this document is hosted in
                        foreach (Visio.Window nextWindow in Global.VisioApp.Windows)
                        {
                            if (nextWindow.Type == (short)Visio.VisWinTypes.visDrawing)
                            {
                                if (nextWindow.Document == this.visioDocument)
                                {
                                    // we found the window
                                    m_reportWindow.ShowWindow(nextWindow, AddonWindowConstants.NrtmAddonWindowMergeId, 1);
                                    m_reportWindow.WindowCaption = Global.GetResourceString("ReportWindow_Caption");
                                    m_reportWindow.Visible = false;
                                    m_reportWindow.Terminate += new AddonWindowWrapper.TerminateEventHandler(this.ResultWindowClosed);

                                    break;
                                }
                            }
                        }
                    }
                }
                catch (NrtmException ex)
                {
                    //Exception from sub function. Pass on to entry point
                    throw new NrtmException("ReportWindow", ex.InnerException);
                }
                catch (Exception ex)
                {
                    //Exception from current function
                    throw new NrtmException("ReportWindow", ex);
                }
                // return the report window
                return m_reportWindow;
            }
        }
        
        #endregion Properties

        #region construction

        /// <summary>
        ///	Constructor
        /// </summary>
        /// <param name="visioAppObject">
        ///	Visio Application object reference
        ///	</param>
        public Document(
            Visio.Document visioDocument)
        {
            if (visioDocument == null)
            {
                return;
            }

            // Generate a UniqueID for this class.  This is used as the key into the
            // Application object's m_documents collection.
            this.UniqueID = System.Guid.NewGuid().ToString();

            // store the Visio.Document reference
            this.visioDocument = visioDocument;
            
            // setup delegate events
            SetupVisioEvents();

            //Load the NRTM menu
            docMenu = new NRTMMenu();
            docMenu.BuildMenu(this);

            //Set active shape as default option
            ipOption = Global.InputDataOption.ActiveShape;

            //Create data table to store monitoring data
            monitorDB = new CreateTables();

            //Configure for NRTM usage
            ConfigureForNRTM();

            this.StatusWindow.Activate();

            return;
        }
        #endregion

        #region Events

        /// <summary>
        /// Resume thread after control return to the application
        /// </summary>
        /// <param name="app"></param>
        void Application_AfterModal(Microsoft.Office.Interop.Visio.Application app)
        {
            if (nrtmDiagramThread != null && nrtmDiagramThread.IsAlive)
            {
                nrtmDiagramThread.Resume();
            }

            if (nrtmMonitorThread != null && nrtmMonitorThread.IsAlive)
            {
                nrtmMonitorThread.Resume();
            }

        }

        /// <summary>
        /// Suspend thread execution when user clicks on document close
        /// </summary>
        /// <param name="app"></param>
        void Application_BeforeModal(Microsoft.Office.Interop.Visio.Application app)
        {
            if (nrtmDiagramThread != null && nrtmDiagramThread.IsAlive)
            {
                nrtmDiagramThread.Suspend();
            }

            if (nrtmMonitorThread != null && nrtmMonitorThread.IsAlive)
            {
                nrtmMonitorThread.Suspend();
            }
            return;
        }

        /// <summary>
        /// Before closing the document clear the events
        /// </summary>
        /// <param name="visioDocument"></param>
        void visioDocument_BeforeDocumentClose(Visio.Document visioDocument)
        {
            try
            {
                // get the document name
                string fullName = visioDocument.FullName.ToLower(CultureInfo.CurrentCulture);

                if (fullName.EndsWith(".vss") ||
                    fullName.EndsWith(".vsx") ||
                    visioDocument.Type == Visio.VisDocumentTypes.visTypeStencil)
                {
                    // no action need to be performed for this document
                    return;
                }
                if (this.visioDocument == visioDocument)
                {
                    //Clear the events set for this document
                    DeleteVisioEvents();
                }
            }
            catch (NrtmException ex)
            {

                //To catch and display exceptions from sub functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                //To catch exceptions from current functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            }
            return;
        }

        /// <summary>
        /// Check if shapes being deleted are being monitored
        /// </summary>
        /// <param name="Selection">Shapes selected to delete</param>
        /// <returns>True to cancel delete</returns>
        bool visioDocument_QueryCancelSelectionDelete(Microsoft.Office.Interop.Visio.Selection Selection)
        {
            try
            {
                if (this.diskMonitoringOn)
                {
                    //Monitoring in progress. Check if select shape are being monitored
                    foreach (Visio.Shape visioShape in Selection)
                    {
                        //Check if Prop.NRTMConfig present and set to true
                        if (ConfigureServerShape.ShapePropertyExist(visioShape, "Prop.NRTMConfig") &&
                            visioShape.get_Cells("Prop.NRTMConfig.Value").get_ResultStr((short)Visio.VisUnitCodes.visNoCast) == "TRUE")
                        {
                            //Shape to be deleted being monitored
                            MessageBox.Show(Global.GetResourceString("Document_ShapeDelete_Text"),
                                Global.GetResourceString("Document_MsgBox_Title"),
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information,
                                MessageBoxDefaultButton.Button1);
                            return true;
                        }
                    }
                }
                if (this.diagramGenerationOn)
                {
                    //Shape delete disabled during diagram generation
                    MessageBox.Show(Global.GetResourceString("Document_ShapeDelete_Diagram"),
                        Global.GetResourceString("Document_MsgBox_Title"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information,
                        MessageBoxDefaultButton.Button1);
                    return true;
                }
            }
            catch (NrtmException ex)
            {

                //To catch and display exceptions from sub functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                //To catch exceptions from current functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            }
            return false;
        }

        /// <summary>
        /// On document close check if monitoring is in progress
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        bool visioDocument_QueryCancelDocumentClose(Microsoft.Office.Interop.Visio.Document doc)
        {
            try
            {
                //Check if diagram generation is on
                if (this.diagramGenerationOn)
                {
                    //Diagram generation in progress. Confirm if user want to close the document
                    DialogResult cancelDiagram = MessageBox.Show(Global.GetResourceString("Document_DiaGen_Close_Text"),
                        Global.GetResourceString("Document_MsgBox_Title"),
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Information,
                        MessageBoxDefaultButton.Button1);

                    if (cancelDiagram == DialogResult.No)
                    {
                        //If user dont want to cancel monitoring return true
                        return true;
                    }
                    else
                    {
                        //If user want to close the document cancel diagram generation
                        StopDiagramGeneration(Global.ThreadStop.Cancel);
                    }
                }

                //Check if disk monitoring on
                if (this.diskMonitoringOn)
                {
                    //Monitoring in progress. Confirm if user want to close the document
                    DialogResult cancelMonitoring = MessageBox.Show(Global.GetResourceString("Document_Monitor_Close_Text"),
                        Global.GetResourceString("Document_MsgBox_Title"),
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Information,
                        MessageBoxDefaultButton.Button1);
                    if (cancelMonitoring == DialogResult.No)
                    {
                        //If user dont want to cancel monitoring return true
                        return true;
                    }
                    else
                    {
                        //If user want to close the document cancel monitoring
                        StopDiskMonitoring(Global.ThreadStop.Cancel);
                    }
                }
            }
            catch (NrtmException ex)
            {

                //To catch and display exceptions from sub functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                //To catch exceptions from current functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            }
            return false;
        }

        /// <summary>
        /// On page delete check if monitoring is in progess
        /// </summary>
        /// <param name="Page"></param>
        /// <returns></returns>
        bool visioDocument_QueryCancelPageDelete(Microsoft.Office.Interop.Visio.Page Page)
        {
            if (this.diskMonitoringOn)
            {
                //Monitoring in progress. Cannot delete the page
                MessageBox.Show(Global.GetResourceString("Document_Page_Delete_Text"),
                    Global.GetResourceString("Document_MsgBox_Title"),
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information,
                    MessageBoxDefaultButton.Button1);
                return true;
            }
            if (this.diagramGenerationOn)
            {
                //Diagram generation in progress. Cannot delete the page
                MessageBox.Show(Global.GetResourceString("Document_Page_Delete_Diagram"),
                    Global.GetResourceString("Document_MsgBox_Title"),
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information,
                    MessageBoxDefaultButton.Button1);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Visio marker event for document
        /// </summary>
        /// <param name="app"></param>
        /// <param name="SequenceNum"></param>
        /// <param name="ContextString"></param>
        internal void vsoApplication_MarkerEvent(Visio.Application visioApplication, int SequenceNum, string ContextString)
        {
            Visio.Document visioDocument = null;
            Visio.Page visioPage = null;
            Visio.Shape visioShape = null;
            string appid = null;
            string cmd = null;

            try
            {
                //Check if valid arguments exist
                if (string.IsNullOrEmpty(ContextString))
                    return;

                //Get the visio objects from the context string
                Global.GetVisioObjects(ContextString, visioApplication, ref visioDocument,
                    ref visioPage, ref visioShape, ref appid, ref cmd);

                //If event not raise for nrtm return
                if (string.Compare(appid, Global.ApplicationID) != 0)
                    return;

                //If event not for current document return
                if (visioDocument != this.visioDocument)
                    return;

                switch (cmd)
                {
                    case Global.CommandStringSelectMachines:
                        using (BaseWizardForm wizardForm = new BaseWizardForm())
                        {
                            wizardForm.ShowDialog();
                        }
                        //Form will be disposed at the end of using
                        break;

                    case Global.CommandStringNRTMOptions:
                        using (Options opt = new Options())
                        {
                            opt.ShowDialog();
                        }
                        //Form will be disposed at the end of using
                        break;

                    case Global.CommandStringHelp:

                        if (File.Exists(Global.AddinHelpFile))
                        {
                            //FileAttributes fileAttribute = FileAttributes.ReadOnly;
                            //File.SetAttributes(Global.AddinHelpFile, fileAttribute);
                            try
                            {
                                FileInfo helpFile = new FileInfo(Global.AddinHelpFile);
                                Process word = new Process();
                                word.StartInfo.FileName = helpFile.FullName;
                                word.Start();
                            }
                            catch (System.ComponentModel.Win32Exception ex)
                            {
                                if (ex.NativeErrorCode==1155) // Message.Contains("No application is associated with the specified file for this operation"))
                                {
                                    MessageBox.Show(Global.GetResourceString("PDF_Viewer_Error"),
                                        Global.GetResourceString("Document_MsgBox_Title"),
                                        MessageBoxButtons.OK, MessageBoxIcon.Error,
                                        MessageBoxDefaultButton.Button1);
                                }
                            }
                        }
                        else
                        {
                            MessageBox.Show(Global.GetResourceString("Invalid_HelpFIle"),
                            Global.GetResourceString("Document_MsgBox_Title"),
                            MessageBoxButtons.OK, MessageBoxIcon.Error,
                           MessageBoxDefaultButton.Button1);
                        }
                        break;

                    case Global.CommandStringStartMonitoring:
                        if (StartMonitoringThread())
                        {
                            //Update the monitor flag for the document
                            this.VisioDocument.DocumentSheet.get_CellsU("User.NRTMMonitor").FormulaU = "TRUE";
                            //Update the menu status for monitoring started
                            docMenu.NRTMMenu_UIBuilder_RefreshUIObject(Global.MenuStateMonitoringInProgress);
                        }
                        break;

                    case Global.CommandStringStopMonitoring:
                        //Stop the active monitoring session
                        StopDiskMonitoring(Global.ThreadStop.Cancel);
                        break;

                    case Global.CommandStringShowStatusWindow:
                        docMenu.NRTMMenu_UIBuilder_RefreshUIObject(Global.MenuStateToggleStatus);
                        if (this.StatusWindow != null)
                        {
                            NRTMMenu.ToggleWindowState(this.StatusWindow);
                        }
                        break;

                    case Global.CommandStringShowReportWindow:
                        docMenu.NRTMMenu_UIBuilder_RefreshUIObject(Global.MenuStateToggleReport);
                        if (this.ReportWindow != null)
                        {
                            NRTMMenu.ToggleWindowState(this.ReportWindow);
                        }
                        break;

                    case Global.CommandStringExportReportToExcel:
                        if (this.ReportWindow != null)
                        {
                            ReportDlg reportDlg = null;
                            reportDlg = (ReportDlg)this.ReportWindow.FormToShow;
                            reportDlg.ExportToExcel();
                        }
                        break;

                    case Global.CommandStringDrill:
                        if (visioShape != null)
                        {
                            using (DiskDetails diskDetailsForm = new DiskDetails())
                            {
                                diskDetailsForm.NRTMDocument = this;
                                diskDetailsForm.DiskDetailsLoad(visioShape);
                                diskDetailsForm.ShowDialog();
                            }
                            //Form will be disposed at the end of using
                        }
                        break;

                    case Global.CommandStringAbout:
                        using (AboutForm abtFrm = new AboutForm())
                        {
                            abtFrm.ShowDialog();
                        }
                        //Form will be disposed at the end of using
                        break;

                    default:
                        break;
                }
            }
            catch (NrtmException ex)
            {
                //To catch and display exceptions from sub functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                //To catch exceptions from current functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            }
        }

        /// <summary>
        /// Set the NRTMAvail & NRTMMonitor flags after document save is complete
        /// </summary>
        /// <param name="app"></param>
        void Application_NoEventsPending(Microsoft.Office.Interop.Visio.Application app)
        {
            try
            {
                if (this.nrtmConfigured && this.documentSaved)
                {
                    //Reset NRTM Avail status
                    this.VisioDocument.DocumentSheet.get_CellsU(
                            "User.NRTMAvail").FormulaU = "TRUE";

                    //Reset NRTM Monitor status
                    this.VisioDocument.DocumentSheet.get_CellsU(
                            "User.NRTMMonitor").FormulaU = monitorStatus;

                    //Reset the save state
                    this.visioDocument.Saved = true;

                    //Reset the saved flag
                    documentSaved = false;
                }
            }
            catch (NrtmException ex)
            {

                //To catch and display exceptions from sub functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                //To catch exceptions from current functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            }

            return;
        }

        /// <summary>
        /// Reset the NRTM Avail and NRTM Monitor flags to disable 
        /// smart tags & view detail option after document is saved
        /// </summary>
        /// <param name="doc"></param>
        void visioDocument_BeforeDocumentSaveOrSaveAs(Microsoft.Office.Interop.Visio.Document doc)
        {
            try
            {
                if (this.nrtmConfigured)
                {
                    string nrtmAvailValue = this.VisioDocument.DocumentSheet.get_CellsU(
                        "User.NRTMAvail").FormulaU;
                    if (nrtmAvailValue == "TRUE")
                    {
                        this.VisioDocument.DocumentSheet.get_CellsU(
                            "User.NRTMAvail").FormulaU = "FALSE";

                        //Save the monitor status to reset after document is saved
                        monitorStatus = this.VisioDocument.DocumentSheet.get_CellsU("User.NRTMMonitor").FormulaU;

                        this.VisioDocument.DocumentSheet.get_CellsU(
                            "User.NRTMMonitor").FormulaU = "FALSE";

                        documentSaved = true;
                    }
                }
            }
            catch (NrtmException ex)
            {

                //To catch and display exceptions from sub functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                //To catch exceptions from current functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            }

            return;
        }

        /// <summary>
        /// Event called on close of status window
        /// </summary>
        private void StatusWindowClosed()
        {
            if (m_statusWindow != null)
            {
                docMenu.NRTMMenu_UIBuilder_RefreshUIObject(Global.MenuStateResetStatus);
                m_statusWindow.Visible = false;
                m_statusWindow = null;
            }
        }

        /// <summary>
        /// Event called on close of report window
        /// </summary>
        private void ResultWindowClosed()
        {
            if (m_reportWindow != null)
            {
                docMenu.NRTMMenu_UIBuilder_RefreshUIObject(Global.MenuStateResetReport);
                m_reportWindow.Visible = false;
                m_reportWindow = null;
            }
        }

        #endregion Events

        #region Methods
        /// <summary>
        /// Setup the event sinks to the Visio.Document class.
        /// </summary>
        private void SetupVisioEvents()
        {
            try
            {
                visioDocument.Application.MarkerEvent += new Microsoft.Office.Interop.Visio.EApplication_MarkerEventEventHandler(vsoApplication_MarkerEvent);
                visioDocument.Application.NoEventsPending += new Microsoft.Office.Interop.Visio.EApplication_NoEventsPendingEventHandler(Application_NoEventsPending);
                visioDocument.Application.BeforeModal += new Microsoft.Office.Interop.Visio.EApplication_BeforeModalEventHandler(Application_BeforeModal);
                visioDocument.Application.AfterModal += new Microsoft.Office.Interop.Visio.EApplication_AfterModalEventHandler(Application_AfterModal);

                visioDocument.ShapeAdded += new Microsoft.Office.Interop.Visio.EDocument_ShapeAddedEventHandler(ConfigureServerShape.VisioApp_ShapeAdded);
                visioDocument.BeforeDocumentClose += new Microsoft.Office.Interop.Visio.EDocument_BeforeDocumentCloseEventHandler(visioDocument_BeforeDocumentClose);
                visioDocument.BeforeDocumentSave += new Microsoft.Office.Interop.Visio.EDocument_BeforeDocumentSaveEventHandler(visioDocument_BeforeDocumentSaveOrSaveAs);
                visioDocument.BeforeDocumentSaveAs += new Microsoft.Office.Interop.Visio.EDocument_BeforeDocumentSaveAsEventHandler(visioDocument_BeforeDocumentSaveOrSaveAs);
                visioDocument.QueryCancelSelectionDelete += new Microsoft.Office.Interop.Visio.EDocument_QueryCancelSelectionDeleteEventHandler(visioDocument_QueryCancelSelectionDelete);
                visioDocument.QueryCancelDocumentClose += new Microsoft.Office.Interop.Visio.EDocument_QueryCancelDocumentCloseEventHandler(visioDocument_QueryCancelDocumentClose);
                visioDocument.QueryCancelPageDelete += new Microsoft.Office.Interop.Visio.EDocument_QueryCancelPageDeleteEventHandler(visioDocument_QueryCancelPageDelete);

            }
            catch (Exception ex)
            {
                //To catch exceptions from current functions
                throw new NrtmException("Setup document events", ex);
            }
            return;
        }

        /// <summary>
        /// Delete visio events before exit
        /// </summary>
        public void DeleteVisioEvents()
        {
            try
            {
                //Clear events
                visioDocument.Application.MarkerEvent -= vsoApplication_MarkerEvent;
                visioDocument.Application.NoEventsPending -= Application_NoEventsPending;

                visioDocument.ShapeAdded -= ConfigureServerShape.VisioApp_ShapeAdded;
                visioDocument.BeforeDocumentSave -= visioDocument_BeforeDocumentSaveOrSaveAs;
                visioDocument.BeforeDocumentSaveAs -= visioDocument_BeforeDocumentSaveOrSaveAs;
                visioDocument.QueryCancelSelectionDelete -= visioDocument_QueryCancelSelectionDelete;
                visioDocument.QueryCancelDocumentClose -= visioDocument_QueryCancelDocumentClose;
                visioDocument.QueryCancelPageDelete -= visioDocument_QueryCancelPageDelete;

                //Remove NRTM menu
                if (docMenu != null)
                {
                    docMenu.RemoveNRTMMenu();
                    docMenu = null;
                }
            }
            catch (Exception ex)
            {
                //To catch exceptions from current functions
                throw new NrtmException("Delete Visio Events", ex);
            }
        }
        
        /// <summary>
        /// Configure document to use with NRTM
        /// </summary>
        private void ConfigureForNRTM()
        {
            try
            {
                // User.NRTMAvail cell
                if (!Convert.ToBoolean(this.VisioDocument.DocumentSheet.get_CellExistsU(
                    Global.DocTemplateUserProp,
                    (short)Visio.VisExistsFlags.visExistsAnywhere)))
                {
                    this.VisioDocument.DocumentSheet.AddNamedRow(
                        (short)Visio.VisSectionIndices.visSectionUser,
                        "NRTMAvail",
                        0);
                }
                this.VisioDocument.DocumentSheet.get_CellsU("User.NRTMAvail").FormulaU = "TRUE";

                // User.NRTMMonitor cell
                if (!Convert.ToBoolean(this.VisioDocument.DocumentSheet.get_CellExistsU(
                    "User.NRTMMonitor",
                    (short)Visio.VisExistsFlags.visExistsAnywhere)))
                {
                    this.VisioDocument.DocumentSheet.AddNamedRow(
                        (short)Visio.VisSectionIndices.visSectionUser,
                        "NRTMMonitor",
                        0);
                }
                this.VisioDocument.DocumentSheet.get_CellsU(
                            "User.NRTMMonitor").FormulaU = "FALSE";


                //Set NRTM configure flag true for this document
                nrtmConfigured = true;
            }
            catch (NrtmException ex)
            {
                //Exception from sub function. Pass on to entry point
                throw new NrtmException("Configure For NRTM", ex.InnerException);
            }
            catch (Exception ex)
            {
                //Exception from current function
                throw new NrtmException("Configure For NRTM", ex);
            }
        }

        /// <summary>
        /// Start disk space monitoring thread
        /// </summary>
        /// <returns>True if start monitoring successful</returns>
        internal bool StartMonitoringThread()
        {
            try
            {
                //Check if diagram generation in progess
                if (diagramGenerationOn == true)
                {
                    MessageBox.Show(Global.GetResourceString("Document_DiagramStart_Text"),
                        Global.GetResourceString("Document_MsgBox_Title"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information,
                        MessageBoxDefaultButton.Button1);
                    //Start monitoring failed. Return False
                    return false;
                }

                //Check if monitoring already in progess
                if (diskMonitoringOn == true)
                {
                    MessageBox.Show(Global.GetResourceString("Document_MonitorStart_Text"),
                        Global.GetResourceString("Document_MsgBox_Title"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information,
                        MessageBoxDefaultButton.Button1);
                    //Start monitoring failed. Return False
                    return false;
                }

                monitorMach = new Monitor();

                nrtmMonitorThread = null;

                //Set monitoring flag to true
                diskMonitoringOn = true;

                //Show status window
                this.StatusWindow.Activate();
                this.StatusWindow.Visible = true;

                //Assign the status window to monitor thread
                monitorMach.StatusWindow = this.StatusWindow;

                //Assign the report window to monitor thread
                this.ReportWindow.Visible = false;

                nrtmMonitorThread = new Thread(new ParameterizedThreadStart(monitorMach.StartDiskMonitoring));

                if (nrtmMonitorThread != null)
                {
                    nrtmMonitorThread.Name = "NRTMDiskSpaceMonitor";
                    nrtmMonitorThread.Start(this);
                }

                //Monitoring thread started. Return True
                return true;
            }
            catch (NrtmException ex)
            {
                //Exception from sub function. Pass on to entry point
                throw new NrtmException("Start Monitoring", ex.InnerException);
            }
            catch (Exception ex)
            {
                //Exception from current function
                throw new NrtmException("Start Monitoring", ex);
            }
        }

        /// <summary>
        /// Stop disk space monitoring thread
        /// </summary>
        /// <param name="cancelledByUser">True if monitoring cancelled by user</param>
        internal void StopDiskMonitoring(Global.ThreadStop threadStatus)
        {
            StatusDlg statusDlg = null;
            ReportDlg reportDlg = null;

            try
            {
                if (diskMonitoringOn == true)
                {
                    //get status window
                    if (this.StatusWindow != null &&
                        this.StatusWindow.Visible == true)
                    {
                        statusDlg = (StatusDlg)this.StatusWindow.FormToShow;
                    }
                    // get the report dialog form
                    if (this.ReportWindow != null)
                    {
                        reportDlg = (ReportDlg)this.ReportWindow.FormToShow;
                    }
                    //Check if aborted by user
                    if (threadStatus == Global.ThreadStop.Cancel)
                    {
                        //Stop monitor scan
                        if (nrtmMonitorThread != null)
                        {
                            nrtmMonitorThread.Abort();
                            nrtmMonitorThread = null;
                        }

                        //Update the abort status
                        if (statusDlg != null)
                        {
                            statusDlg.UpdateStatus(string.Empty);
                            statusDlg.UpdateStatus(Global.GetResourceString("StatusDlg_Update_Cancel"));
                        }
                    }
                    else if (threadStatus == Global.ThreadStop.Complete)
                    {
                        //Thread ended normally
                        if (statusDlg != null)
                        {
                            // notify the end of the monitoring
                            statusDlg.UpdateStatus(string.Empty);
                            statusDlg.UpdateStatus(Global.GetResourceString("StatusDlg_Update_Complete"));
                        }
                    }
                    else if (threadStatus == Global.ThreadStop.Abort)
                    {
                        //Thread ended with error
                        if (statusDlg != null)
                        {
                            // notify the end of the monitoring
                            statusDlg.UpdateStatus(string.Empty);
                            statusDlg.UpdateStatus(Global.GetResourceString("StatusDlg_Update_Abort"));
                        }
                    }
                    //Populate report window with data
                    reportDlg.ShowGridData();
                    //Show report window
                    m_reportWindow.Visible = true;
                }
            }
            catch (System.Threading.ThreadAbortException)
            {
                //Ignore thread abort exception
            }
            catch (NrtmException ex)
            {
                //Exception from sub function. Pass on to entry point
                throw new NrtmException("Stop Monitoring", ex.InnerException);
            }
            catch (Exception ex)
            {
                //Exception from current function
                throw new NrtmException("Stop Monitoring", ex);
            }
            finally
            {
                //Change status of menu items of the current document
                docMenu.NRTMMenu_UIBuilder_RefreshUIObject(Global.MenuStateMonitoringCompleted);

                // reset the running flag
                diskMonitoringOn = false;

                // disable the cancel button and reset dialog result
                if (statusDlg != null)
                {
                    statusDlg.CancelButtonEnabled(false);
                    statusDlg.DialogResult = DialogResult.None;
                }
            }
        }

        /// <summary>
        /// Stop diagram generation thread
        /// </summary>
        /// <param name="threadStatus">Status of the thread</param>
        internal void StopDiagramGeneration(Global.ThreadStop threadStatus)
        {
            StatusDlg statusDlg = null;

            try
            {
                if (diagramGenerationOn == true)
                {
                    //get status window
                    if (this.StatusWindow != null &&
                        this.StatusWindow.Visible == true)
                    {
                        statusDlg = (StatusDlg)this.StatusWindow.FormToShow;
                    }

                    //Check if aborted by user
                    if (threadStatus == Global.ThreadStop.Cancel)
                    {
                        //Stop diagram generation
                        if (nrtmDiagramThread != null)
                        {
                            nrtmDiagramThread.Abort();
                            nrtmDiagramThread = null;
                        }

                        //Update the abort status
                        if (statusDlg != null)
                        {
                            statusDlg.UpdateStatus(string.Empty);
                            statusDlg.UpdateStatus(Global.GetResourceString("StatusDlg_Update_CancelDiagram"));
                        }
                    }
                    else if (threadStatus == Global.ThreadStop.Complete)
                    {
                        //Thread ended normally
                        if (statusDlg != null)
                        {
                            // notify the end of the monitoring
                            statusDlg.UpdateStatus(string.Empty);
                            statusDlg.UpdateStatus(Global.GetResourceString("StatusDlg_Update_CompleteDiagram"));
                        }
                    }
                    else if (threadStatus == Global.ThreadStop.Abort)
                    {
                        //Thread ended with error
                        if (statusDlg != null)
                        {
                            // notify the end of the monitoring
                            statusDlg.UpdateStatus(string.Empty);
                            statusDlg.UpdateStatus(Global.GetResourceString("StatusDlg_Update_AbortDiagram"));
                        }
                    }
                }
            }
            catch (System.Threading.ThreadAbortException)
            {
                //Ignore thread abort exception
            }
            catch (NrtmException ex)
            {
                //Exception from sub function. Pass on to entry point
                throw new NrtmException("Stop Diagram Generation", ex.InnerException);
            }
            catch (Exception ex)
            {
                //Exception from current function
                throw new NrtmException("Stop Diagram Generation", ex);
            }
            finally
            {
                //Change status of menu items of the current document
                docMenu.NRTMMenu_UIBuilder_RefreshUIObject(Global.MenuStateDiagramCreated);

                // reset the running flag
                diagramGenerationOn = false;

                // disable the cancel button and reset dialog result
                if (statusDlg != null)
                {
                    statusDlg.CancelButtonEnabled(false);
                    statusDlg.DialogResult = DialogResult.None;
                }
            }
        }

        #endregion Methods
    }
}
